package com.jintian.smart.kernel.flowable.flowable.cmd;

import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;

import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.variable.api.types.VariableType;
import org.flowable.variable.api.types.VariableTypes;
import org.flowable.variable.service.HistoricVariableService;
import org.flowable.variable.service.impl.persistence.entity.VariableInstanceEntityImpl;

/**
 * 添加历史变量值，例如作废原因、挂起原因天数等。属性必须以“hi_varinst:”开头
 */
public class AddHistoricVariableCmd implements Command<Void> {
    public static final int HistoricVariable_ProcessInstance = 0;
    public static final int HistoricVariable_TaskInstance = 1;
    public static final String varNamePrefix = "hi_varinst:";

    private final String instanceId;
    private final int processOrTask;

    private final Map<String, Object> variables;

    public AddHistoricVariableCmd(String instanceId, int processOrTask, Map<String, Object> variables) {
        this.processOrTask = processOrTask;
        this.instanceId = instanceId;
        this.variables = variables;
    }

    private void addProcessInstanceHistoricVariable(HistoricVariableService historicVariableService, HistoricProcessInstanceEntity pi, VariableTypes vriableTypes, Date date) {
        for (Entry<String, Object> var : variables.entrySet()) {
            if (var.getKey().startsWith(varNamePrefix)) {
                VariableInstanceEntityImpl variableInstanceEntity = new VariableInstanceEntityImpl();
                VariableType type = vriableTypes.findVariableType(var.getValue());
                variableInstanceEntity.setType(type);
                variableInstanceEntity.setProcessDefinitionId(pi.getProcessDefinitionId());
                variableInstanceEntity.setProcessInstanceId(pi.getProcessInstanceId());
                variableInstanceEntity.setExecutionId(pi.getId());
                variableInstanceEntity.setTaskId(null);
                variableInstanceEntity.setName(var.getKey().substring(varNamePrefix.length()));
                variableInstanceEntity.setValue(var.getValue());
                historicVariableService.createAndInsert(variableInstanceEntity, date);
            }
        }
    }

    private void addTaskHistoricVariable(HistoricVariableService historicVariableService, HistoricTaskInstanceEntity task, VariableTypes vriableTypes, Date date) {
        for (Entry<String, Object> var : variables.entrySet()) {
            if (var.getKey().startsWith(varNamePrefix)) {
                VariableInstanceEntityImpl variableInstanceEntity = new VariableInstanceEntityImpl();
                VariableType type = vriableTypes.findVariableType(var.getValue());
                variableInstanceEntity.setType(type);
                variableInstanceEntity.setProcessDefinitionId(task.getProcessDefinitionId());
                variableInstanceEntity.setProcessInstanceId(task.getProcessInstanceId());
                variableInstanceEntity.setExecutionId(task.getExecutionId());
                variableInstanceEntity.setTaskId(task.getId());
                variableInstanceEntity.setName(var.getKey().substring(varNamePrefix.length()));
                variableInstanceEntity.setValue(var.getValue());
                historicVariableService.createAndInsert(variableInstanceEntity, date);
            }
        }
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (variables == null || variables.isEmpty()) {
            return null;
        }
        ProcessEngineConfiguration processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        Date date = processEngineConfiguration.getClock().getCurrentTime();
        HistoricVariableService historicVariableService = CommandContextUtil.getHistoricVariableService(commandContext);
        if (this.processOrTask == HistoricVariable_TaskInstance) {
            HistoricTaskInstanceEntity task = CommandContextUtil.getHistoricTaskService(commandContext).getHistoricTask(this.instanceId);
            this.addTaskHistoricVariable(historicVariableService, task, ((ProcessEngineConfigurationImpl) processEngineConfiguration).getVariableTypes(), date);

        } else if (this.processOrTask == HistoricVariable_ProcessInstance) {
            HistoricProcessInstanceEntity pi = CommandContextUtil.getHistoricProcessInstanceEntityManager(commandContext).findById(this.instanceId);
            this.addProcessInstanceHistoricVariable(historicVariableService, pi, ((ProcessEngineConfigurationImpl) processEngineConfiguration).getVariableTypes(), date);
        }
        return null;
    }
}